home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 1 / LSD Compendium Deluxe 1.iso / a / text / manipulation / snap164.lha / saveilbm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-30  |  5.6 KB  |  213 lines

  1. #if __SASC
  2. #include "snap.h"
  3. #endif
  4.  
  5. /* Auto: make
  6. */
  7. #include <setjmp.h>
  8.  
  9. #define SAFE(cond, jmp_buf)  { if (!(cond)) longjmp(jmp_buf,-1); }
  10.  
  11. IMPORT BYTE TranspBuf[];
  12.  
  13. #define ID(a,b,c,d) ((a << 24L) | (b << 16L) | (c << 8L) | (d))
  14.  
  15. struct ckHdr {
  16.     LONG ChunkName;
  17.     LONG ChunkSize;
  18. };
  19.  
  20. struct BitMapHeader
  21. {
  22.    UWORD w,h;
  23.    WORD  x,y;
  24.    UBYTE nPlanes;
  25.    UBYTE masking;
  26.    UBYTE compression;
  27.    UBYTE pad1;
  28.    UWORD transparentColor;
  29.    UBYTE xAspect, yAspect;
  30.    WORD  pageWidth, pageHeight;
  31. };
  32.  
  33. struct ckHdr FORM = {
  34.     ID('F','O','R','M'),
  35.     0L
  36. };
  37. LONG TYPE = ID('I','L','B','M');
  38.  
  39. struct ckHdr BMHD = {
  40.     ID('B','M','H','D'),
  41.     sizeof(struct BitMapHeader)
  42. };
  43. struct BitMapHeader BMHdr = {
  44.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  45. };
  46.  
  47. struct ckHdr CAMG = {
  48.     ID('C','A','M','G'),
  49.     4L
  50. };
  51. ULONG ViewMode = NULL;
  52.  
  53. struct ckHdr CMAP = {
  54.     ID('C','M','A','P'),
  55.     0L
  56. };
  57.  
  58. struct ckHdr BODY = {
  59.     ID('B','O','D','Y'),
  60.     0L
  61. };
  62.  
  63. UBYTE *buf;
  64. WORD bufcnt;
  65. ULONG totalsize;
  66.  
  67. WORD bump(struct CBFHandle *CBFH, WORD cnt, UBYTE *dataptr, WORD size)
  68. {
  69.     REGISTER LONG tsize = size;
  70.     if (tsize) {
  71.         totalsize += tsize + 1;     /* Don't forget the count-byte */
  72.     }
  73.     if (bufcnt + tsize + 1 >= 4096 || tsize == 0) {
  74.         if (CBFWrite(CBFH, (char *)buf, (LONG)bufcnt) == -1L) {
  75.             return 0;
  76.         }
  77.         bufcnt = 0;
  78.     }
  79.     buf[bufcnt++] = cnt;
  80.     CopyMem((char *)dataptr, (char *)&buf[bufcnt], tsize);
  81.     bufcnt += tsize;
  82.     return 1;
  83. }
  84.  
  85. ULONG WriteBody(BM, CBFH)
  86. struct BitMap *BM;
  87. struct CBFHandle *CBFH;
  88. {
  89.     WORD scanline, plane;
  90.     REGISTER WORD bpr = BM->BytesPerRow;
  91.     REGISTER WORD i, j;
  92.     LONG offset = 0L;
  93.     REGISTER UBYTE data;
  94.     REGISTER UBYTE *bd;
  95.     jmp_buf failure;
  96.  
  97.     totalsize = 0L;
  98.  
  99.     if (!(buf = AllocMem(4096L, MEMF_PUBLIC))) {
  100.         return NULL;
  101.     }
  102.  
  103.     if (setjmp(failure)) {
  104.         FreeMem(buf, 4096L);
  105.         return NULL;
  106.     }
  107.  
  108.     bufcnt = 0;
  109.     for (scanline = 0; scanline < BM->Rows; ++scanline) {
  110.         for (plane = 0; plane < BM->Depth; ++plane) {
  111.             bd = BM->Planes[plane]+offset;
  112.             i = 1;
  113.             j = bpr - 1;
  114.             data = bd[0];
  115.             while (j) {
  116.                 if (bd[i] == data) {        /* Equal bytes? */
  117.                     --i;                    /* First equal byte */
  118.                     if (i > 0) {            /* Old "random" data to save */
  119.                         SAFE(bump(CBFH, (WORD)(i - 1), bd, i), failure);
  120.                     }
  121.                     bd = &bd[i];        /* Start of equal bytes */
  122.                     i = 2;              /* 0 & 1 is equal       */
  123.                     --j;
  124.                     while (i < 128 && j && bd[i] == data) {
  125.                         ++i;
  126.                         --j;
  127.                     }
  128.                     SAFE(bump(CBFH, (WORD)-(i - 1), &bd[i - 1], (WORD)1), failure);
  129.                     goto new_block;
  130.                 } else {                    /* Not equal. Check block range */
  131.                     if (i == 128) {         /* Block limit                  */
  132.                         SAFE(bump(CBFH, (WORD)(i - 1), bd, i), failure);
  133. new_block:
  134.                         bd = &bd[i];  /* Start new block              */
  135.                         i = 0;
  136.                         if (j == 0) {
  137.                             break;
  138.                         }
  139.                     }
  140.                 }
  141.                   /* Different byte or a new start */
  142.                 data = bd[i];               /* New possible equal       */
  143. next_byte:
  144.                 ++i;
  145.                 --j;
  146.             }
  147.             if (i != 0) {                   /* Data to save */
  148.                 SAFE(bump(CBFH, (WORD)(i - 1), bd, i), failure);
  149.             }
  150.         }
  151.         offset += BM->BytesPerRow;
  152.     }
  153.       /* Flush any bytes left if the buffer */
  154.     SAFE(bump(CBFH, (WORD)0, NULL, (WORD)0), failure);
  155.     FreeMem(buf, 4096L);
  156.     return totalsize;
  157. }
  158.  
  159. WORD SaveGS(GS, CBFH)
  160. struct GfxSnap *GS;
  161. struct CBFHandle *CBFH;
  162. {
  163.     ULONG BODYPos;
  164.     UBYTE *oldtitle;
  165.     jmp_buf failure;
  166.  
  167.     oldtitle = GS->window->Title;
  168.     SetWindowTitles(GS->window, "Saving...", (char *)-1);
  169.  
  170.     BMHdr.w = GS->BM.BytesPerRow * 8;
  171.     BMHdr.h = GS->height;
  172.     BMHdr.x = BMHdr.y = 0;
  173.     BMHdr.nPlanes = GS->depth;
  174.     BMHdr.masking = 0;
  175.     BMHdr.compression = 1;
  176.     BMHdr.transparentColor = dectoint(TranspBuf);
  177.     BMHdr.xAspect = BMHdr.xAspect = 1;
  178.     BMHdr.pageWidth = GS->pagew;
  179.     BMHdr.pageHeight = GS->pageh;
  180.     ViewMode = GS->viewmode;
  181.  
  182.     CMAP.ChunkSize = (LONG)3 * (GS->viewmode & HAM ? 16 : 1L << GS->depth);
  183.  
  184.     CBFInit(CBFH);
  185.  
  186.     if (setjmp(failure)) {
  187.         CBFEndWrite(CBFH);
  188.         return 0;
  189.     }
  190.  
  191.     SAFE(CBFWrite(CBFH, (char *)&FORM,
  192.       (LONG)(sizeof(FORM) + sizeof(TYPE) +
  193.              sizeof(BMHD) + sizeof(BMHdr) +
  194.              sizeof(CAMG) + sizeof(ViewMode) +
  195.              sizeof(CMAP))) != -1L, failure);
  196.     SAFE(CBFWrite(CBFH, (char *)&GS->rgb[0], CMAP.ChunkSize) != -1L, failure);
  197.     BODYPos = CBFSeek(CBFH, 0L, OFFSET_CURRENT);
  198.     SAFE(CBFWrite(CBFH, (char *)&BODY, (LONG)sizeof(BODY)) != -1L, failure);
  199.     SAFE(BODY.ChunkSize = WriteBody(&GS->BM, CBFH), failure);
  200.     FORM.ChunkSize = BODYPos - sizeof(FORM) + sizeof(BODY) + BODY.ChunkSize;
  201.     if (FORM.ChunkSize & 1) {                       /* Odd size */
  202.         SAFE(CBFWrite(CBFH, "X", 1L) != -1L, failure);
  203.         ++FORM.ChunkSize;
  204.     }
  205.     CBFSeek(CBFH, 0L, OFFSET_BEGINNING);
  206.     CBFWrite(CBFH, (char *)&FORM, (LONG)sizeof(FORM));
  207.     CBFSeek(CBFH, BODYPos, OFFSET_BEGINNING);
  208.     CBFWrite(CBFH, (char *)&BODY, (LONG)sizeof(BODY));
  209.     CBFEndWrite(CBFH);
  210.     SetWindowTitles(GS->window, (char *)oldtitle, (char *)-1);
  211.     return 1;
  212. }
  213.